package org.xq.modules.order.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.xq.modules.order.domain.TProduct;
import org.xq.modules.order.domain.TProductRecord;
import org.xq.modules.order.mapper.TProductDao;
import org.xq.modules.order.mapper.TProductRecordDao;

import javax.annotation.PostConstruct;

@Slf4j
@RestController
@RequestMapping("rabbit")
public class RabbitController {
    @Autowired
    RabbitTemplate rabbitTemplate;

    @PostConstruct
    private void init(){
        /**
         * 消息发送到交换器Exchange后触发回调。
         * 使用该功能需要开启确认，spring-boot中配置如下：
         * spring.rabbitmq.publisher-confirms = true
         */
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean b, String s) {
                if (b) {
                    System.out.println("消息已确认 cause:{"+s+"} - {"+correlationData+"}");
                } else {
                    System.out.println("消息未确认 cause:{"+s+"} - {"+correlationData+"}");
                }
            }
        });
        /**
         * 通过实现ReturnCallback接口，
         * 如果消息从交换器发送到对应队列失败时触发
         * 比如根据发送消息时指定的routingKey找不到队列时会触发
         * 使用该功能需要开启确认，spring-boot中配置如下：
         * spring.rabbitmq.publisher-returns = true
         */
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
                log.error("消息被退回:{}", message);
                log.error("消息使用的交换机:{}", exchange);
                log.error("消息使用的路由键:{}", routingKey);
                log.error("描述:{}", replyText);
            }
        });
    }

    private int userId=0;
    //开始测试抢单
    @GetMapping("/begin")
    public void begin(){
        userId++;
        this.send(userId);
    }

    @GetMapping("/send")
    public String send(Integer messge){
        //第一个参数：交换机名字  第二个参数：Routing Key的值  第三个参数：传递的消息对象
        rabbitTemplate.convertAndSend("amq.direct","test",messge);
        return "发送消息成功";
    }


    @Autowired
    private TProductDao testDao;
    @Autowired
    private TProductRecordDao recordDao;
    public void robbingProduct(Integer userId){
        TProduct product = testDao.queryByProductNo("No123321");
        if (product != null && product.getTotal() > 0) {
            //更新库存表，库存量减少1。返回1说明更新成功。返回0说明库存已经为0
            int i = testDao.updateProduct("No123321");
            if(i>0){
                //插入记录
                recordDao.insert(new TProductRecord("No123321", userId));
                //发送短信
                log.info("用户{}抢单成功", userId);
            }else {
                log.error("用户{}抢单失败", userId);
            }
        } else {
            log.error("用户{}抢单失败", userId);
        }

    }
}
